#ifndef STRAY_MESH_MESH_H
#define STRAY_MESH_MESH_H

#include <SmartPtr/SharedPtr.h>
#include <Container.h>
#include <Graphics.h>
#include "../Resource.h"

namespace Stray {
namespace Resource {

struct MeshCreationParam
{
	struct Vertices
	{
		Stray::Uint32 vertexCount_;
		Stray::Vector<Stray::Uint8>::type verticesByteArray_;
	};

	struct Indices
	{
		Stray::Uint32 indexCount_;
		Stray::Vector<Stray::Uint8>::type indices_;
	};

	struct Subset
	{
		Subset():materialId_(String(), String(), String(), String()){}
		ResourceID materialId_;
		Stray::Vector<Stray::Uint32>::type jointIndexTable_;
		Stray::Uint32 startIndex_;
		Stray::Uint32 triangleCount_;
	};

	typedef Stray::SharedPtr<Stray::Core::Graphics::VertexLayoutTable>::type VertexLayoutTablePtr;
	typedef Stray::SharedPtr<Vertices>::type VerticesPtr;
	typedef Stray::SharedPtr<Indices>::type IndicesPtr;
	typedef Stray::SharedPtr<Subset>::type SubsetPtr;

	typedef Stray::Vector<VertexLayoutTablePtr>::type VertexLayoutTableArray;
	typedef Stray::Vector<VerticesPtr>::type VerticesArray;
	typedef Stray::Vector<SubsetPtr>::type SubsetArray;

	VertexLayoutTableArray layoutTables_;
	VerticesArray verticesArray_;
	IndicesPtr spIndices_;
	SubsetArray subsetArray_;
};

class Subset;
typedef Stray::SharedPtr<Subset>::type SubsetPtr;

class Mesh : public Resource
{
	friend class MeshFactory;
public:
	static const char type_[];
private:
	typedef Stray::Core::Graphics::IndexBufferPtr IndexBufferPtr;
	typedef Stray::Core::Graphics::VertexBufferPtr VertexBufferPtr;
	typedef Stray::Core::Graphics::VertexLayoutPtr VertexLayoutPtr;
	typedef Stray::Vector<VertexBufferPtr>::type VertexBuffers;
	typedef Stray::Vector<SubsetPtr>::type Subsets;
	Mesh(const ResourceID& id);
public:
	void load(Bool isAsync = B_FALSE);

	IndexBufferPtr getIndexBuffer() const;
	VertexLayoutPtr getVertexLayout() const;
	Stray::Uint32 getVertexBufferCount() const;
	VertexBufferPtr getVertexBuffer(Stray::Uint32 index) const;
	Stray::Uint32 getSubsetCount() const;
	SubsetPtr getSubset(Stray::Uint32 index) const;
private:
	IndexBufferPtr spIndexBuffer_;
	VertexLayoutPtr spVertexLayout_;
	VertexBuffers vertexBuffers_;
	Subsets subsets_;

	void build(const MeshCreationParam& param);
	VertexLayoutPtr createVertexLayout(const MeshCreationParam::VertexLayoutTableArray& tableArray);
	VertexBufferPtr createVertexBuffer(const MeshCreationParam::VerticesPtr& vertices);
	IndexBufferPtr createIndexBuffer(const MeshCreationParam::IndicesPtr& indices);
	SubsetPtr createSubset(const MeshCreationParam::SubsetPtr& subset);
};

typedef Stray::SharedPtr<Mesh>::type MeshPtr;

class Material;
typedef SharedPtr<Material>::type MaterialPtr;

class Subset
{
	friend class Mesh;
public:
	typedef Stray::Vector<Stray::Uint32>::type JointIndexTable;
private:
	Subset():materialId_(String(), String(), String(), String()){}
public:
	ResourceID materialId_;
	JointIndexTable spJointIndexTable_;
	Stray::Uint32 startIndex_;
	Stray::Uint32 triangleCount_;
};

}
}

#endif 